package com.cy.pj.goods.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import javax.sql.DataSource;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**  此对象为一个商品数据层访问对象,现在要求在此类中定义一个方法,
    这个方法基于JDBC从从数据库获取商品信息,并将其封装到map集合,
    要求一个行记录一个map对象(key为表中字段名,值为字段名对应的值),
    多个map存储到list集合. @Repository此注解通常用于描述数据层实现类对象,
    本质上就是一个特殊的@Component, 都是要交给spring框架管理的一个Bean对象*/


@Repository//此注解一般用于描述数据逻辑层的具体实现对象,此对象要交给spring管理
public class DefaultGoodsDao implements GoodsDao {
    @Autowired
    private DataSource dataSource;//hikariCP

    /**查询商品信息,一行记录映射为内存中的一个map对象*/
    @Override
    public List<Map<String, Object>> findGoods()  {
        Connection a = null;
        Statement c = null;
        ResultSet d = null;
        String b = "select * from tb_goods";
        try {
            //1,获取jdbc连接
            a = dataSource.getConnection();
            //2,创建Ststement对象,基于此对象发送SQL
            c = a.createStatement();
            //3,发送SQL,执行查询
            d = c.executeQuery(b);
            //4,处理结果集(将所有记录封装到List<Map<String, Object>>)
            List<Map<String, Object>> list = new ArrayList<>();
            while (d.next()) {//循环一次取一行,一行记录映射为一个map对象
                list.add(rowMap(d));//将存储了一行记录的map对象再存储到list集合
            }
            return list;
        } catch (SQLException z) {//SQLException 是一种检查异常
            z.printStackTrace();
            //有异常的话就执行不到return list;方法没有返回值,就会报错
            throw new RuntimeException(z);//转换为非检查异常(编译时不检测的异常)
            //return null;//加上throw new RuntimeException(z); 以后就可以省略下面的return null;
        }finally {
            //5,释放资源
           close(a,c,d);
        }
    }

    private Map<String, Object> rowMap(ResultSet d) throws SQLException {
        //方法1映射
        //必须写在循环内,否则多行数据存入一个Map集合中时,相同的key,值(value)会被覆盖
        Map<String, Object> map=new HashMap<>();
        /*rowMap.put("id",d.getInt("id"));
        rowMap.put("name",d.getString("name"));
        rowMap.put("remark",d.getString("remark"));
        rowMap.put("createdTime",d.getTimestamp("createdTime"));*/
        //方法2映射
       ResultSetMetaData e=d.getMetaData();//获取元数据(包括表中的字段名)
       int columnCount =e.getColumnCount();//获取列的数量
        for (int i = 1; i <=columnCount ; i++) {
            map.put(e.getColumnLabel(i+1), d.getObject(e.getColumnLabel(i+1)));
             //getColumnLabel(i+1);获取表中字段名或字段名对应的别名
        }
        return map;
    }

    private void close(Connection a, Statement c, ResultSet d) {
        if(a!=null){
            try {
                a.close();
            } catch (Exception x) {
                x.printStackTrace();
            }
        }
        if(c!=null){
            try {
                c.close();
            } catch (Exception x) {
                x.printStackTrace();
            }
        }
        if(d!=null){
            try {
                d.close();
            } catch (Exception x) {
                x.printStackTrace();
            }
        }
        //这里的连接是返回到了池中
    }



}